--=====
--Arcade Mode
--=====
--Debug all the things!
_G.themeDebug = false;
_G.DebugGrade = 0; --Hint: Check ScreenEvaluationTest overlay
_G.CurrentFakeCourse = nil;
_G.DebugGoToExtra = false; --Test the extra intro screen.
_G.DebugGoToOMES = false;
_G.AlwaysAllowExtra = true; --Can always enter the Extra Stage.
_G.shouldEnterTutorial = false;
_G.currentStoryChapter = 1 --Selected story chapter when debug testing
--[[
Because GetCurrentStageIndex can't be reset and I need to account for the tutorial...
Also it's 1-indexed because fuck you. That means the tutorial is stage 0.
]]
_G.StageIndex = 1;

--[[
1: Normal
2: Extra
3: OMES
]]
_G.StageType = 1;

--[[
Apparently StepMania doesn't keep information on the score history. So I'm doing it myself.

]]

--SM might have its own reset() function so I named it differently
function reset_THSM()
	--Warn("THSM, Starting up!");
	_G.CurrentFakeCourse = nil;
	MBSTATE:Reset();
	_G.shouldEnterTutorial = false;
	_G.StageIndex = 1;
	GAMESTATE:SetTemporaryEventMode(false);
end;

function GetChoiceNames()
	if _G.themeDebug then
		return "1,2,ED,3,DB,TH"
	else
		return "1,2,Edit,3,4"
	end
end;

function GetOptionsMenuNames()
	if _G.themeDebug then
		return "GraphicSound,KeyConfig,TestInput,Sync,Profiles,Credits,CheatCodes,SysOption"
	else
		return "GraphicSound,KeyConfig,TestInput,Sync,Profiles,Credits,CheatCodes"
	end
end;

local gradeNames = {
    "AAA",
    "AA",
    "A",
    "B",
    "C",
    "D",
    "E",
    "INVALID!"
};

_G.diffColors = {
	Beginner = Color("HoloBlue"),
	Easy     = Color("HoloOrange"),
	Medium   = color("1,0,1,1"),
	Hard     = Color("Green"),
	Challenge= Color("Red"),--color("#9900ff"),
	Edit     = Color("White")
};

function getGradeLetter(grade)
  --[[if type(grade) ~= "number" then
	SCREENMAN:SystemMessage("Error: getGradeLetter is for NUMBERS, you idiot. You gave: "..grade);
	return "AAA";
  end;]]
	assert(grade, "Grade was nil!");
	if grade < #gradeNames then
		--Because lua arrays start at 1...
		--You can't preform arithmatic on an enum for some odd reason, so it has to be turned into a number.
		--grade = grade + 1;
		local gradeLetter = gradeNames[Grade:Reverse()[grade+1]];
		--[[if grade == nil then
			SCREENMAN:SystemMessage("Grade was nil!!");
			return "F";
		end;]]
		return gradeLetter;
	else
		return "F";
	end;
end;

function gradeToNumber(grade)
	return Grade:Reverse()[grade]
end;

function branch_tutorial()
	if _G.shouldEnterTutorial then
		local song = SONGMAN:FindSong("How To Play")
		GAMESTATE:SetCurrentSong(song);
		GAMESTATE:SetCurrentPlayMode("PlayMode_Regular");
		GAMESTATE:SetCurrentStyle("Single");
		local steps = song:GetOneSteps('StepsType_Dance_Single', 0);
		GAMESTATE:SetCurrentSteps('PlayerNumber_P1',steps);
		local can, reason = GAMESTATE:CanSafelyEnterGameplay()
		if can then
			return "ScreenGameplay";
		else
			SCREENMAN:SystemMessage("Can't enter gameplay! "..reason);
			return "ScreenTitleMenu";
		end;
	else
		_G.StageIndex = 1;
		return EnterFakeCourse();
	end;
end;

--Set the song using the current stage index.
function setFCSong()
	local i = _G.StageIndex;
	assert(_G.CurrentFakeCourse);
	local s = _G.CurrentFakeCourse:GetCourseEntry(i-1):GetSong();
	--[[
	It's not the course class' job to pick a song if you put in a wildcard, apparently.
	So if there's no song, just pick a random one I guess
	]]
	--assert(s);
	if not s then
		Warn("No song found for stage "..i..", picking a random one");
		lua.Flush();
		s = SONGMAN:GetRandomSong()
	end;
	local difficulty = MBSTATE:GetDifficulty(GAMESTATE:GetMasterPlayerNumber());
	assert(s:HasStepsTypeAndDifficulty('StepsType_Dance_Single', difficulty),"setFCSong: The song "..s:GetMainTitle().." (probably a randomly picked one) didn't have valid steps. Giving up.");
	local steps = s:GetOneSteps('StepsType_Dance_Single', difficulty);
	Warn("SETTING STAGE "..i..": "..s:GetMainTitle());
	GAMESTATE:SetCurrentSong(s);
	GAMESTATE:SetCurrentSteps(GAMESTATE:GetMasterPlayerNumber(),steps);
end;

function EnterArcadeMode()
	assert(MBSTATE:GetCharacter(GAMESTATE:GetMasterPlayerNumber()),"Tried to enter arcade mode without a character!");
	local c = SONGMAN:FindCourse(MBSTATE:GetCharacter(GAMESTATE:GetMasterPlayerNumber()))
	if not c then
		SCREENMAN:SystemMessage("Can't enter gameplay! Course "..MBSTATE:GetCharacter(GAMESTATE:GetMasterPlayerNumber()).." is misspelled or not installed!");
		return "ScreenTitleMenu";
	end;
	--GAMESTATE:SetCurrentCourse(c);
	_G.CurrentFakeCourse = c;
	GAMESTATE:SetCurrentPlayMode("PlayMode_Regular");
	GAMESTATE:SetCurrentStyle("Single");
	GAMESTATE:SetTemporaryEventMode(true);
	setFCSong();
	local can, reason = GAMESTATE:CanSafelyEnterGameplay()
	if can then
		return SongOrStory();
	else
		SCREENMAN:SystemMessage("Can't enter gameplay! "..reason);
		return "ScreenTitleMenu";
	end;
end;

function SongOrStory()
	local course = _G.CurrentFakeCourse;
	assert(course);
	local NumCourseEntries = #course:GetCourseEntries();
	
	--The stage you are about to enter. Which starts at 1.
	local n = _G.StageIndex;
	
	--If the player failed.
	if STATSMAN:GetCurStageStats():AllFailed() then
		return "ScreenGameOver";
	end;
	
	if n <= NumCourseEntries then
		
		local dir = course:GetCourseDir():sub(1, -5);
		
		--If 1 before the final stage, it means they're on the EX stage
		--[[if (n == NumCourseEntries and NumCourseEntries == 5) or (n == NumCourseEntries-1 and NumCourseEntries > 5) then
			--Need to A all stages.
			if getLowestGradeOfCourse() < 3 or _G.AlwaysAllowExtra then
				_G.StageType = 2;
			else
				return "ScreenStoryEnd";
			end;
		--And if they're on the final stage and there's six (or more) stages, then they're on the One More Extra Stage. I think.
		elseif n == NumCourseEntries and NumCourseEntries > 5 then
			--Need to AA all stages.
			if getLowestGradeOfCourse() < 2 then
				_G.StageType = 3;
			else
				return "ScreenStoryEnd";
			end;
		--If they're after the OMES stage?
		elseif n > NumCourseEntries then
			return "ScreenStoryEnd";
		end]]
		
		--[[
		Set it before entering a new screen, since at this point we've determined
		that the player has passed and they're eligible for another song.
		]]
		setFCSong();
		if FILEMAN:DoesFileExist(dir.."/"..n..".lua") then
			SCREENMAN:SystemMessage("Entering stage "..n.." story.");
			return "ScreenStory"
		else
			MBSTATE:SetEnemyCharacter(MBSTATE:GetRandomEncounter());
			SCREENMAN:SystemMessage(dir.."/"..n..".lua not found, going to gameplay screen.");
			--Warn and Trace doesn't fucking work
			Trace("Trying to enter ScreenStageInformation for next song. Current Stage: "..n);
			return "ScreenStageInformation"
		end;
	else
		return "ScreenStoryEnd";
	end;
end;

function getLowestGradeOfCourse()
	return STATSMAN:GetWorstGrade();
end

--Handle fake course or music select
function AfterEvaluation()
	--If the player is in story mode...
	if _G.CurrentFakeCourse ~= nil then
		--if completed n stage, go to stage n+1...
		_G.StageIndex = _G.StageIndex + 1;
		return SongOrStory();
	else
		--Trace("No course found, using Branch.AfterEvaluation()");
		return Branch.AfterEvaluation();
	end;
end;

--Because it's useful
function Actor:Cover()
	self:scaletocover(0,0,SCREEN_RIGHT,SCREEN_BOTTOM);
end;

--THSM Credits!
local thsm_credits = {
	name="MBAACC StepMania Credits",
	"Coding, Arcade Mode, and more by Rhythm Lunatic",
	"Some VNText help by Kyzentun",
	"IIDX style level display by Jousway from QuadIIDX",
	"Melty Blood is owned by French Bread. No copyright infringement intended!"
};
StepManiaCredits.AddSection(thsm_credits);


--Various helper functions
function ListActorChildren(frame)
	if frame:GetNumChildren() == 0 then
		return "No children in frame.";
	end
	local list = frame:GetNumChildren().." children: ";
	local children = frame:GetChildren()
	for key,value in pairs(children) do
		list = list..key..", ";
	end
	return list;
end
